﻿using System;
using System.Collections.Generic;
using System.Linq;
using ElectronicCommerce.Framework.Ioc.Interceptor.Configuration;
using ElectronicCommerce.Framework.Ioc.Interceptor.Infos;
using ElectronicCommerce.Framework.Ioc.Windsor;
using MethodInfo = ElectronicCommerce.Framework.Ioc.Interceptor.Configuration.MethodInfo;

using Castle.Core.Interceptor;
namespace ElectronicCommerce.Framework.Ioc.Interceptor
{
    /// <summary>
    /// Intercepter Facator
    /// </summary>
    public static class IntercepterFacator
    {
        #region Fileds

        private static readonly Dictionary<Type, IInterceptor[]> DicInfo =
            new Dictionary<Type, IInterceptor[]>();

        #endregion

        #region Method

        public static IInterceptor[] Creator(Type serviceType)
        {
            #region Create by dic

            if (DicInfo.ContainsKey(serviceType))
            {
                return DicInfo[serviceType];
            }

            #endregion

            #region Check

            if (IntercepterConfigHelper.IntercepterConfig == null)
            {
                return null;
            }

            #endregion

            List<IInterceptor> interceptors = Initial(new object());

            #region Add to dic

            if (interceptors != null)
            {
                DicInfo.Add(serviceType, interceptors.ToArray());
                return interceptors.ToArray();
            }

            #endregion

            return null;
        }

        private static List<IInterceptor> Initial(object objLock)
        {
            lock (objLock)
            {
                List<IInterceptor> interceptors = null;

                #region Create

                var infos = IntercepterConfigHelper.IntercepterConfig.IntercepterInfos;
                foreach (var info in infos)
                {
                    #region Create all interface

                    if (info.IsAllServices)
                    {
                        if (interceptors == null)
                        {
                            interceptors = new List<IInterceptor>();
                        }
                        interceptors.Add((IntercepterBase)Activator.CreateInstance(info.IntercepterType));
                        continue;
                    }

                    #endregion

                    #region Create no all interface

                    IEnumerable<ServiceInfo> serviceInfos;
                    if ((serviceInfos = info.ServiceCollection) != null
                        && serviceInfos.Count() > 0)
                    {
                        if (interceptors == null)
                        {
                            interceptors = new List<IInterceptor>();
                        }

                        #region Find all methods

                        var methodList = serviceInfos.Where(c => c.Methods != null && c.Methods.Count > 0).Select(c => c.Methods);
                        if (methodList != null && methodList.Count() > 0)
                        {
                            #region Get all methods

                            List<MethodInfo> useMethodInfos = new List<MethodInfo>();
                            List<MethodInfo> notUseMethodInfos = new List<MethodInfo>();
                            foreach (var methods in methodList)
                            {

                                if (methods.Count(c => c.IsUseIntercepter) > 0)
                                {
                                    useMethodInfos.AddRange(methods.Where(C => C.IsUseIntercepter));
                                }
                                if (methods.Count(c => !c.IsUseIntercepter) > 0)
                                {
                                    notUseMethodInfos.AddRange(methods.Where(C => !C.IsUseIntercepter));
                                }
                            }

                            #endregion

                            #region Create instance

                            if (useMethodInfos.Count > 0 || notUseMethodInfos.Count > 0)
                            {
                                var instance = (IntercepterBase)Activator.CreateInstance(
                                    info.IntercepterType);
                                instance.NotUseMethodInfos = notUseMethodInfos.Count > 0 ? notUseMethodInfos : null;
                                instance.UseMethodInfos = useMethodInfos.Count > 0 ? useMethodInfos : null;
                                interceptors.Add(instance);
                            }

                            #endregion
                        }

                        #endregion
                    }

                    #endregion
                }

                #endregion

                return interceptors;
            }
        }

        #endregion
    }
}
